package com.xdf.wxbebarrel.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.thoughtworks.xstream.XStream;
import com.xdf.wxbebarrel.model.ExternalTemplateMsg;
import com.xdf.wxbebarrel.model.User;
import com.xdf.wxbebarrel.model.templateMessage.MetaData;
import com.xdf.wxbebarrel.model.templateMessage.TemplateMessageData;
import com.xdf.wxbebarrel.model.templateMessage.TemplateMessageWrapper;
import com.xdf.wxbebarrel.service.ReqsLogService;
import com.xdf.wxbebarrel.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 发送模板消息的工具类
 * @author chanchaw
 * @create 2022-11-24 20:39
 */
@Component
public class TemplateMsgUtils {

    @Autowired
    private ReqsLogService dbLog;
    private static final ObjectMapper mapper = new ObjectMapper();
    private static final String TEMPLATE_ID_AUDIT = "IRUGdjkPP2p8sOXR-g-xtDsnvGkD_hyt-W083VeNo-I";

    @Autowired
    private UserService userService;

    public Boolean pushTemplateMsgGeneric(ExternalTemplateMsg record,String token) {
        if( record == null ) {
            dbLog.insert("传入了空的ExternalTemplateMsg对象，不会推送模板消息");
            return false;
        }

        List<MetaData> metaList = record.getMetaList();
        if( metaList == null || metaList.size()<=0 ){
            dbLog.insert("通用外部推送模板消息时，消息体为空，不会推送消息。");
            return false;
        }

        TemplateMessageWrapper msg = strArray2TemplateMessageMetaData(metaList);
        msg.setTemplate_id(record.getTemplateId());
        pushMsg(msg,record.getOpenidList(),token);
        return true;
    }

    private void pushMsg(TemplateMessageWrapper msg, List<String> openIds,@NotNull String token) {
        if( msg == null ) {
            dbLog.insert("推送模板消息时传入了空消息");
            throw new BusinessException("空消息不可推送！");
        }
        if( openIds == null || openIds.size()<=0 ) {
            dbLog.insert("推送模板消息时传入的微信 openid 是空");
            throw new BusinessException("没有设置接收推送消息的微信opend，无法推送！");
        }

        dbLog.insert(msg.toString(),"推送的模板消息");
        dbLog.insert(openIds.toString(),"模板消息推送给的微信号");

        XStream stream = new XStream();
        stream.processAnnotations(TemplateMessageWrapper.class);

        for(String item:openIds){
            msg.setTouser(item);
            String jsonString = null;
            try {
                jsonString = mapper.writeValueAsString(msg);
            } catch (JsonProcessingException e) {
                dbLog.insert("转换消息对象为jsonString时出现异常","TemplateMsgUtils#pushMsg");
                throw new RuntimeException(e);
            }
            String reqUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token;
            try {
                String ret = HttpUtils.postJson( reqUrl, jsonString);
            } catch (Exception e) {
                dbLog.insert("使用HttpUtils推送模板消息时出现异常","TemplateMsgUtils#pushMsg");
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 微信服务号菜单项上URL连接需要拼接固定格式的参数供微信服务器解析
     * 本方法传入H5页面的原始URL，返回需要微信代理的 URL
     * @param rawUrl 原始URL，类似 https://www.xdfznh.club/wxpadfe/meter/PayByCard.html
     * @return 返回微信代理的URL，字符串类型
     */
    private String getProxyUrl(String rawUrl){
        String encodedUrl = URLEncoder.encode(rawUrl);
        String proxyUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
                DevMaterial.JZY.APPID + "&redirect_uri=" + encodedUrl +
                "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
        return proxyUrl;
    }

    private TemplateMessageWrapper strArray2TemplateMessageMetaData(List<MetaData> metaList){
        TemplateMessageData data = new TemplateMessageData();

        if( metaList == null || metaList.size()<=0 ){
            data.setFirst(setDefaultColor(new MetaData("这个人很懒")));
            data.setKeyword1(setDefaultColor(new MetaData("没有设置任何内容就想推送模板消息")));
            data.setKeyword2(setDefaultColor(new MetaData(DatetimeUtils.formatNow())));
            data.setKeyword3(setDefaultColor(new MetaData("")));
            data.setKeyword4(setDefaultColor(new MetaData("")));
            data.setKeyword5(setDefaultColor(new MetaData("")));
            data.setRemark(setDefaultColor(new MetaData("")));
            data.setUrl("");// 详情页的地址（字符串），所以没有颜色
        }else{
            // 加工外部传入的 MetaData ，设置默认字体颜色
            // 只有最后一个序号7的没有颜色 - 详情页的连接地址，所以没有颜色
            data.setFirst(setDefaultColor(metaList.get(0)));
            data.setKeyword1(setDefaultColor(metaList.get(1)));
            data.setKeyword2(setDefaultColor(metaList.get(2)));
            data.setKeyword3(setDefaultColor(metaList.get(3)));
            data.setKeyword4(setDefaultColor(metaList.get(4)));
            data.setKeyword5(setDefaultColor(metaList.get(5)));
            data.setRemark(setDefaultColor(metaList.get(6)));
            data.setUrl(metaList.get(7).getValue());// 详情页的地址（字符串），所以没有颜色
        }

        TemplateMessageWrapper msg = new TemplateMessageWrapper();
        msg.setData(data);
        msg.setMiniprogram(null);
        msg.setUrl(metaList.get(7).getValue());

        return msg;
    }

    private MetaData setDefaultColor(MetaData record){
        String color = Optional.ofNullable(record.getColor()).orElse(SysConst.TEMPLATE_MESSAGE_BLUE);
        record.setColor(color);
        return record;
    }

    public void pushAuditors(List<String> msg,String token){
        List<User> userList = userService.selectAllAuditors();
        if(userList == null || userList.size()==0) return;
        List<String> openIds = userList.stream().map(item -> item.getOpenId()).collect(Collectors.toList());

        if(msg.size()<8){
            for (int i = 0; i < 8-msg.size(); i++) {
                msg.add("");
            }
        }
        List<MetaData> metaDataList = new ArrayList<>();
        for (int i = 0; i < msg.size(); i++) {
            metaDataList.add(new MetaData(msg.get(i)));
        }

        ExternalTemplateMsg templateMsg = new ExternalTemplateMsg();
        templateMsg.setTemplateId(TEMPLATE_ID_AUDIT);
        templateMsg.setOpenidList(openIds);
        templateMsg.setMetaList(metaDataList);
        pushTemplateMsgGeneric(templateMsg,token);
    }
}
